﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace _027_解释器模式
{
    class Interpreter
    {
        //字符和函数名一一映射
        Dictionary<string, string> characterDict;
        string assmblName = "027-第二十七章-解释器模式";
        string nameSpace = "_027_解释器模式";

        public Interpreter(string path)
        {
            MapSetting map = ReadJsonFile(path);
            InitDict(map);
        }

        public Expression GetExpression(string content)
        {
            if(characterDict.TryGetValue(content ,out string value))
            {
                var temp = (Expression)Assembly.Load(assmblName).CreateInstance(string.Format("{0}.{1}", nameSpace, value));//可以使用对象池模式，不用每次都创建
                if (temp != null)
                {
                    return temp;
                }
            }
            return null;
        }

        private MapSetting ReadJsonFile(string path)
        {
            string set = File.ReadAllText(path);
            MapSetting mapSet = JsonConvert.DeserializeObject<MapSetting>(set);
            if (mapSet != null)
            {
                return mapSet;
            }
            else
                return null;
        }

        private void InitDict(MapSetting map)
        {
            characterDict = new Dictionary<string, string>();
            if (map != null)
            {
                foreach (var item in map.AllMaps)
                {
                    if (!characterDict.ContainsKey(item.Character))
                    {
                        characterDict.Add(item.Character, item.ClassName);
                    }
                }
            }
        }
    }

    public class MapSetting
    {
        public List<MapItem> AllMaps { get; set; }
    }

    public class MapItem
    {
        /// <summary>
        /// 字符名称
        /// </summary>
        public string Character { get; set; }
        /// <summary>
        /// 类名称
        /// </summary>
        public string ClassName { get; set; }
    }
}
